package org.aj.web.exception.alarm;

import org.aj.web.exception.prop.AlarmProperties;
import org.aj.web.exception.prop.MailProperties;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;

import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * description 邮件告警处理类
 *
 * @author aj
 * date 2024/10/27 18:17
 */
public class MailHandler implements AlarmHandler{

    private static final Logger log = LoggerFactory.getLogger(MailHandler.class);

    //记录邮件的发送次数
    private static final Map<String,AtomicInteger> URI_SEND_MAIL_COUNT = new ConcurrentHashMap<>();
    //记录这一轮邮件发送的最后时间
    private static final Map<String,Long>  URI_LAST_SENT_MAIL_TIME = new ConcurrentHashMap<>();


    private JavaMailSender javaMailSender;
    private ApplicationContext applicationContext;

    private AlarmProperties alarmProperties;

    public MailHandler(JavaMailSender javaMailSender, ApplicationContext applicationContext,AlarmProperties alarmProperties) {
        this.javaMailSender = javaMailSender;
        this.applicationContext = applicationContext;
        this.alarmProperties = alarmProperties;
    }

    @Override
    public boolean needSendAlarm() {
        MailProperties mailProperties = alarmProperties.getMailProperties();
        return null != javaMailSender &&  null != mailProperties && null != mailProperties.getReceiveMailAddr()
                && mailProperties.getReceiveMailAddr().length > 0;
    }

    @Override
    public boolean sendAlarmTimeIsRipe(String requestUri) {
        boolean needSendMail = false;
        if(!URI_LAST_SENT_MAIL_TIME.containsKey(requestUri)){
            //记录次数
            if(URI_SEND_MAIL_COUNT.containsKey(requestUri)){
                needSendMail = isNeedSendMail(requestUri);

            }else{
                //log.info("初始化。。。。");
                if(null == URI_SEND_MAIL_COUNT.putIfAbsent(requestUri,new AtomicInteger(1))){
                    //log.info("初始化成功。。。。");
                    needSendMail = true;
                }else{
                    //log.info("已经初始化过了。。。开始计数"+URI_SEND_MAIL_COUNT.containsKey(requestUri));
                    needSendMail = isNeedSendMail(requestUri);
                }

            }

        }else{

            //判断是否到了开始下一轮了
            if(null != URI_LAST_SENT_MAIL_TIME.get(requestUri) && (System.currentTimeMillis() - URI_LAST_SENT_MAIL_TIME.get(requestUri)
                    > alarmProperties.getSendInterval().toMillis())){
                //重新记录
                int currentCount = URI_SEND_MAIL_COUNT.get(requestUri).intValue();
                //log.info("当前次数"+currentCount);
                if(URI_SEND_MAIL_COUNT.get(requestUri).compareAndSet(currentCount,1)){
                    //log.info("重新记录。。。。");
                    URI_LAST_SENT_MAIL_TIME.remove(requestUri);
                    URI_SEND_MAIL_COUNT.get(requestUri).set(1);

                }else{
                    //记录次数 这里暂时不考虑马上并发超过阈值
                    URI_SEND_MAIL_COUNT.get(requestUri).incrementAndGet();
                    //log.info("再次记录次数。。。。"+URI_SEND_MAIL_COUNT.get(requestUri).intValue());
                }
                needSendMail = true;
            }

        }

        return needSendMail;

    }

    @Override
    public void sendAlarm(String alarmMsg, String title) {
        SimpleMailMessage mesg=new SimpleMailMessage();
        mesg.setSubject(title);
        mesg.setFrom(alarmProperties.getMailProperties().getSendMailAddr());
        mesg.setText(alarmMsg);
        mesg.setTo(alarmProperties.getMailProperties().getReceiveMailAddr());
        //设置发送时间
        mesg.setSentDate(Calendar.getInstance().getTime());

        //把这封邮件发送出去
        if(!StringUtils.isEmpty(alarmProperties.getAlarmThreadPoolExecutorBeanName())){
            Object asyncBean = applicationContext.getBean(alarmProperties.getAlarmThreadPoolExecutorBeanName(), Executor.class);

            if(null == asyncBean){
                log.error("根据配置的类路径并没有从spring容器里面找到对应的bean,故无法进行异步发送。。。");
                return;
            }

            if(! (asyncBean instanceof Executor)){
                log.error("根据配置的类路径从spring容器里面找到的bean,不是java.util.concurrent.Executor的子类。。。");
                return;
            }

            //进行异步发送
            ((Executor)asyncBean).execute(new Runnable() {
                @Override
                public void run() {
                    log.info("开始发送邮件。。。。");
                    javaMailSender.send(mesg);
                    log.info("开始发送邮件结束。。。。");
                }
            });

        }else{
            log.info("开始发送邮件。。。。");
            javaMailSender.send(mesg);
            log.info("开始发送邮件结束。。。。");
        }
    }

    private boolean isNeedSendMail(String requestUri) {
        if (URI_SEND_MAIL_COUNT.get(requestUri).incrementAndGet() <= alarmProperties.getSendMaxCount()) {
            if (URI_SEND_MAIL_COUNT.get(requestUri).intValue() == alarmProperties.getSendMaxCount()) {
                //记录最后一次的发送时间
                URI_LAST_SENT_MAIL_TIME.put(requestUri, System.currentTimeMillis());
                //log.info("记录最后一次时间。。。");
            }

            return true;
        } else {
            URI_SEND_MAIL_COUNT.put(requestUri, new AtomicInteger(alarmProperties.getSendMaxCount()));
            return false;
        }

    }
}
